<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>this指向</title>

    <link rel="stylesheet" href="../css/reveal/reveal.css">

    <!-- PPT主题，可以在/css/reveal/theme/中选择其他主题，目前暂时只能使用该模板 -->
    <link rel="stylesheet" href="../css/reveal/theme/ptt.css">

    <!-- syntax highlighting 代码高亮主题 -->
    <link rel="stylesheet" href="../lib/reveal/css/zenburn.css">

    <!-- 打印和PDF输出样式 -->
    <script>
        var link = document.createElement( 'link' );
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = window.location.search.match( /print-pdf/gi ) ? '../css/reveal/print/pdf.css' : '../css/reveal/print/paper.css';
        document.getElementsByTagName( 'head' )[0].appendChild( link );
    </script>
</head>
<body>
<img src="../img/demo/logo.png" alt="" usemap="#pttmap" class="base-logo">
<map name="pttmap">
    <area shape="rect" coords="0,0,276,58" href="http://www.jnshu.com" alt="" target="_blank"/>
</map>
<div class="reveal">
    <div class="slides">
        <section>
            <h2>js中的this指向</h2>
            <p>分享人：文世豪</p>
        </section>
        <section>
            <p>目录</p>
            <p>1.背景介绍</p>
            <p>2.知识剖析</p>
            <p>3.常见问题</p>
            <p>4.解决方案</p>
            <p>5.编码实战</p>
            <p>6.扩展思考</p>
            <p>7.参考文献</p>
            <p>8.更多讨论</p>
        </section>
        <section>
            <h3>1.背景介绍</h3>
        </section>
        <section>
            <p>this的迷之指向</p>
            <section>
                <pre>
                    <code>
                        var obj = {
                        foo: function(){
                        console.log(this)
                        }
                        }
                        var bar = obj.foo
                        obj.foo() // 打印出的 this 是 obj
                        bar() // 打印出的 this 是 window
                        请解释最后两行函数的值为什么不一样。
                    </code>
                </pre>
            </section>
        </section>
        <section>
            <h3>2.知识剖析</h3>
        </section>
        <section>
            <section>
                <pre>
                    <code>

                        //ES5函数调用的3种形式


                        func(p1, p2)
                        obj.child.method(p1, p2)
                        func.call(context, p1, p2)

                    </code>
                </pre>
                </section>
            <section>
                <pre>
                    <code>
                        //语法糖


                        func(p1, p2) 等价于
                        func.call(undefined, p1, p2)

                        obj.child.method(p1, p2) 等价于
                        obj.child.method.call(obj.child, p1, p2)
                    </code>
                </pre>
            </section>
            <section>
                <pre>
                    <code>
                        //第三种

                        func.call(context, p1, p2)


                        //this，就是上面代码中的 context。
                    </code>
                </pre>
            </section>
        </section>
        <section>
            <h3>3.常见问题</h3>
        </section>
        <section>
            <section>
              <pre>
                <code>
                    function func(){
                        console.log(this)
                    }

                    func()

                    //等价于

                    function func(){
                        console.log(this)
                    }

                    func.call(undefined) // 可以简写为 func.call()
                    //上面是打印出来是什么？
                </code>
              </pre>
             </section>
            <section>
                按理说打印出来的 this 应该就是 undefined 了吧，但浏览器里有一条规则：

                如果你传的 context 就 null 或者 undefined，那么 window 对象就是默认的 context（严格模式下默认 context 是 undefined）
                因此上面的打印结果是 window。
            </section>

        </section>
        <section>
            <h3>4.解决方案</h3>
        </section>
        <section>
            <pre>
                <code>
                    //如果你希望这里的 this 不是 window，很简单：

                    func.call(obj) // 那么里面的 this 就是 obj 对象了
                 </code>
          </pre>
        </section>
        <section>
           <pre>
                <code>
                    obj.child.method(p1, p2) 的 this 如何确定

                    var obj = {
                    foo: function(){
                    console.log(this)
                    }
                    }

                    obj.foo()
                    按照「转换代码」，我们将 obj.foo() 转换为

                    obj.foo.call(obj)
                    好了，this 就是 obj。搞定。
                </code>
          </pre>
        </section>
        <section>
            <h3>5.编码实战</h3>
            <section>
                   <pre>
                        <code>
                           回到题目


                            var obj = {
                            foo: function(){
                            console.log(this)
                            }
                            }

                            var bar = obj.foo
                            obj.foo() // 转换为 obj.foo.call(obj)，this 就是 obj
                            bar()
                            // 转换为 bar.call()
                            // 由于没有传 context
                            // 所以 this 就是 undefined
                            // 最后浏览器给你一个默认的 this —— window 对象
                        </code>
                  </pre>
             </section>
        </section>
        </section>
        <section>
            <h3>6.扩展思考</h3>
        </section>
        <section>
            <p>问题1：全局执行</p>
            <p class="fragment">问题2：纯粹的函数调用</p>
            <p class="fragment">问题3：严格模式: 'use strict';</p>
            <p class="fragment">问题4：作为对象的方法调用</p>
            <p class="fragment">问题5：构造函数使用</p>
            <p class="fragment">问题6：箭头函数</p>
        </section>
        <section>
            <h3>7.参考文献</h3>
        </section>
        <section>
            <p>参考一：<a href="https://gold.xitu.io/post/5857dad461ff4b00686cf97a" target="_blank">this 的值到底是什么？一次说清楚</a></p>
            <p>参考一：<a href="https://zhuanlan.zhihu.com/p/24107744" target="_blank">JavaScript 中的 this</a></p>
        </section>
        <section>
            <h3>8.更多讨论</h3>
        </section>
        <section>
            <p>this里面还有那些坑</p>
        </section>
        <section>
            <h4>鸣谢</h4>
            <p>感谢小伙伴们观看</p>
            <p><small>文世豪</small></p>
        </section>

    </div>
</div>

<script src="../lib/reveal/js/head.min.js"></script>
<script src="../lib/reveal/reveal.js"></script>

<script>

    // 以下为常见配置属性的默认值
    // {
    // 	controls: true, // 是否在右下角展示控制条
    // 	progress: true, // 是否显示演示的进度条
    // 	slideNumber: false, // 是否显示当前幻灯片的页数编号，也可以使用代码slideNumber: 'c / t' ，表示当前页/总页数。
    // 	history: false, // 是否将每个幻灯片改变加入到浏览器的历史记录中去
    // 	keyboard: true, // 是否启用键盘快捷键来导航
    // 	overview: true, // 是否启用幻灯片的概览模式，可使用"Esc"或"o"键来切换概览模式
    // 	center: true, // 是否将幻灯片垂直居中
    // 	touch: true, // 是否在触屏设备上启用触摸滑动切换
    // 	loop: false, // 是否循环演示
    // 	rtl: false, // 是否将演示的方向变成RTL，即从右往左
    // 	fragments: true, // 全局开启和关闭碎片。
    // 	autoSlide: 0, // 两个幻灯片之间自动切换的时间间隔（毫秒），当设置成 0 的时候则禁止自动切换，该值可以被幻灯片上的 ` data-autoslide` 属性覆盖
    // 	transition: 'default', // 切换过渡效果，有none/fade/slide/convex/concave/zoom
    // 	transitionSpeed: 'default', // 过渡速度，default/fast/slow
    // 	mouseWheel: true, //是否启用通过鼠标滚轮来切换幻灯片
    // }

    // 初始化幻灯片
    Reveal.initialize({
        history: true,
        dependencies: [
            { src: '../plugin/markdown/marked.js' },
            { src: '../plugin/markdown/markdown.js' },
            { src: '../plugin/notes/notes.js', async: true },
            { src: '../plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }
        ]
    });
</script>
</body>
</html>
